<template>
  <div class="actual-api-detail">
    <el-form :model="editForm" :rules="editFormRules" ref="editForm" label-width="0">
      <div class="content-divider first">
        <div class="clearfix">
          <div class="number">01</div>
          <div class="divider-title">基本信息<br />Essential information</div>
          <div class="bg"></div>
        </div>
      </div>
      <el-row :gutter="20">
        <el-col :span="24">
          <div class="source-item">
            <div class="star"></div>
            <div class="source-title linear-blue">API名称</div>
            <div class="source-content">
              <el-form-item prop="apiNm">
                <el-input v-model="editForm.apiNm" placeholder="请输入API名称" :disabled="!editable"></el-input>
              </el-form-item>
            </div>
          </div>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="12">
          <div class="source-item">
            <div class="star"></div>
            <div class="source-title linear-purpose">请求方式</div>
            <div class="source-content">
              <el-form-item prop="apiReqType">
                <el-select v-model="editForm.apiReqType" :disabled="!editable">
                  <el-option label="---" value=""></el-option>
                  <el-option
                    v-for="item in $dictList('$api_request_type')"
                    :key="item.key"
                    :label="item.value"
                    :value="item.key"
                  ></el-option>
                </el-select>
              </el-form-item>
            </div>
          </div>
        </el-col>
        <el-col :span="12">
          <div class="source-item">
            <div class="star"></div>
            <div class="source-title linear-purpose">格式结果</div>
            <div class="source-content">
              <el-form-item prop="apiRespFormat">
                <el-select v-model="editForm.apiRespFormat" :disabled="!editable">
                  <el-option label="---" value=""></el-option>
                  <el-option
                    v-for="item in apiRespFormatList"
                    :key="item.val"
                    :label="item.label"
                    :value="item.val"
                  ></el-option>
                </el-select>
              </el-form-item>
            </div>
          </div>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="24">
          <div class="source-item">
            <div class="star"></div>
            <div class="source-title linear-green">请求路径</div>
            <div class="source-content">
              <el-form-item prop="apiPath">
                <el-input v-model="editForm.apiPath" placeholder="请输入请求路径" :disabled="!editable"></el-input>
              </el-form-item>
            </div>
          </div>
        </el-col>
      </el-row>
      <el-row :gutter="20">
        <el-col :span="24">
          <div class="source-item desc-item">
            <div class="source-title linear-cyan">API说明</div>
            <div class="source-content">
              <el-form-item prop="apiDesc">
                <el-input
                  placeholder="请输入API说明"
                  v-model="editForm.apiDesc"
                  type="textarea"
                  :maxlength="1000"
                  :rows="5"
                  resize="none"
                  :show-word-limit="true"
                  :disabled="!editable"
                ></el-input>
              </el-form-item>
            </div>
          </div>
        </el-col>
      </el-row>
      <div class="content-divider second">
        <div class="clearfix">
          <div class="number">02</div>
          <div class="divider-title">参数信息<br />Parameter information</div>
          <div class="bg"></div>
        </div>
      </div>
      <el-row :gutter="20">
        <el-col :span="24">
          <div class="source-item params-item">
            <div class="source-title">
              <span><icon-svg name="iconArts"></icon-svg></span><br />
              参数信息
            </div>
            <div class="source-content">
              <el-form-item prop="apiReqContext" class="code-input" :class="{ 'disable-item': !editable }">
                <textarea id="api-req-box"></textarea>
                <el-input v-model="editForm.apiReqContext" type="textarea" :style="codeStyle"></el-input>
              </el-form-item>
            </div>
          </div>
        </el-col>
      </el-row>
      <div class="content-divider third">
        <div class="clearfix">
          <div class="number">03</div>
          <div class="divider-title">返回结果<br />Return result</div>
          <div class="bg"></div>
        </div>
      </div>
      <div class="result-wrap">
        <el-row class="result-title">
          <el-col :span="8">Code</el-col>
          <el-col :span="16">Description</el-col>
        </el-row>
        <div v-for="(item, index) in editForm.apiRespContext" :key="index" class="result-item">
          <el-row>
            <el-col :span="8" align="center">
              <template v-if="item.code === 200 && index === 0">{{ item.code }}</template>
              <el-form-item
                :prop="'apiRespContext.' + index + '.code'"
                :rules="[
                  { required: true, message: 'code编码不能为空', trigger: 'blur' },
                  { type: 'number', message: 'code只能输入数字', trigger: 'blur' }
                ]"
                v-else
              >
                <el-input-number
                  placeholder="请输入code编码"
                  v-model="item.code"
                  :step-strictly="true"
                  :disabled="!editable"
                ></el-input-number>
              </el-form-item>
            </el-col>
            <el-col :span="16">
              <el-form-item
                :prop="'apiRespContext.' + index + '.desc'"
                :rules="[{ required: true, message: '描述信息不能为空', trigger: 'blur' }]"
              >
                <el-input placeholder="请输入描述信息" v-model="item.desc" :disabled="!editable"></el-input>
              </el-form-item>
              <template v-if="item.code === 200 && index === 0">
                <p>Example Value</p>
                <el-form-item
                  :prop="'apiRespContext.' + index + '.example'"
                  :rules="[
                    { validator: isJSON, trigger: 'blur' },
                    { required: true, message: '示例数据不能为空', trigger: 'blur' }
                  ]"
                  class="result-text-box code-input"
                  :class="{ 'disable-item': !editable }"
                >
                  <textarea id="api-resp-box"></textarea>
                  <el-input v-model="item.example" type="textarea" resize="none" :style="codeStyle"></el-input>
                </el-form-item>
              </template>
            </el-col>
          </el-row>
          <div class="result-handler" v-if="editable">
            <el-button icon="el-icon-plus" type="primary" size="mini" circle @click="addResult(index)"></el-button>
            <el-button
              icon="el-icon-minus"
              type="primary"
              size="mini"
              circle
              @click="deleteResult(index)"
              v-if="item.code !== 200 && index !== 0"
            ></el-button>
          </div>
        </div>
      </div>
    </el-form>
  </div>
</template>

<script>
import CodeMirror from 'codemirror'
export default {
  props: {
    drawerType: {
      type: String,
      default: 'view'
    }
  },
  data() {
    const isJSON = (rule, value, callback) => {
      if (!value) return callback()
      try {
        var obj = JSON.parse(value)
        if (obj && typeof obj === 'object') {
          return callback()
        } else {
          return callback(new Error('请输入正确的JSON格式数据'))
        }
      } catch (e) {
        return callback(new Error('请输入正确的JSON格式数据'))
      }
    }
    const checkPath = (rule, value, callback) => {
      if (!value) {
        return callback(new Error('请求路径不能为空'))
      } else {
        let patt = /^\/[a-zA-Z0-9_{}/]*[a-zA-Z0-9_}]$/
        if (!patt.test(value)) {
          return callback(new Error('请求路径只能以/开头,由字母, 数字, / , _ ，{}, 等字符组成,并且不能以/结尾'))
        } else {
          return callback()
        }
      }
    }
    return {
      apiRespFormatList: [{ label: 'JSON', val: 1 }, { label: 'XML', val: 2 }],
      editForm: {
        apiId: '',
        apiNm: '',
        apiPath: '',
        apiReqType: '',
        apiRespFormat: '',
        apiDesc: '',
        apiReqContext: '',
        apiRespContext: [{ code: 200, desc: 'OK', example: '' }]
      },
      editFormRules: {
        apiNm: [
          { required: true, message: '接口名称不能为空', trigger: 'blur' },
          { max: 64, message: '接口名称不能超过64个字符', trigger: 'blur' }
        ],
        apiPath: [
          { validator: checkPath, trigger: 'blur' },
          { max: 100, message: '请求路径不能超过100个字符', trigger: 'blur' }
        ],
        apiReqType: [{ required: true, message: '请求方式不能为空', trigger: 'change' }],
        apiRespFormat: [{ required: true, message: '格式结果不能为空', trigger: 'change' }],
        apiDesc: [{ max: 1000, message: 'API说明不能超过1000个字符', trigger: 'blur' }],
        apiReqContext: [
          { validator: isJSON, trigger: 'blur' },
          { max: 1000, message: '参数信息不能超过1000个字符', trigger: 'blur' }
        ]
      },
      apiReqEditor: null,
      apiRespEditor: null,
      codeStyle: {
        height: 0,
        overflow: 'hidden'
      }
    }
  },
  computed: {
    editable() {
      return this.drawerType === 'edit'
    }
  },
  methods: {
    isJSON(rule, value, callback) {
      if (!value) return callback()
      try {
        var obj = JSON.parse(value)
        if (obj && typeof obj === 'object') {
          return callback()
        } else {
          return callback(new Error('请输入正确的JSON格式数据'))
        }
      } catch (e) {
        return callback(new Error('请输入正确的JSON格式数据'))
      }
    },
    init(apiId) {
      this.editForm.apiId = apiId
      this.getApiDetail()
      this.$nextTick(() => this.initText())
    },
    initText() {
      if (!this.apiReqEditor) {
        this.apiReqEditor = CodeMirror.fromTextArea(document.getElementById('api-req-box'), {
          mode: 'application/json',
          lineWrapping: true,
          foldGutter: true,
          readOnly: !this.editForm ? 'nocursor' : false,
          gutters: ['CodeMirror-foldgutter']
        })
      }
      this.apiReqEditor.setValue(this.editForm.apiReqContext)
      this.apiReqEditor.refresh()
      if (this.editable) this.apiReqEditor.on('blur', this.resreshReq)
      if (!this.apiRespEditor) {
        this.apiRespEditor = CodeMirror.fromTextArea(document.getElementById('api-resp-box'), {
          mode: 'application/json',
          lineWrapping: true,
          foldGutter: true,
          readOnly: !this.editable,
          gutters: ['CodeMirror-foldgutter']
        })
      }
      let resp = this.editForm.apiRespContext.find(item => item.code === 200)
      this.apiRespEditor.setValue(resp ? resp.example : {})
      this.apiRespEditor.refresh()
      if (this.editable) this.apiRespEditor.on('blur', this.resreshResp)
    },
    resreshReq() {
      let content = this.apiReqEditor.getValue()
      this.editForm.apiReqContext = content
      this.$refs.editForm.validateField('apiReqContext')
    },
    resreshResp() {
      let content = this.apiRespEditor.getValue()
      this.editForm.apiRespContext[0].example = content
      this.$refs.editForm.validateField('apiRespContext.0.example')
    },
    getApiDetail() {
      this.$ajax({
        url: this.$ajax.setUrl(`index/indexApi/${this.editForm.apiId}`),
        method: 'get',
        params: this.$ajax.setParams()
      }).then(({ data }) => {
        if (data && data.code === '0') {
          if (data.data) {
            this.editForm.apiNm = data.data.apiNm
            this.editForm.apiPath = !this.editable ? data.data.apiUrl : data.data.apiPath
            this.editForm.apiRespFormat = data.data.apiRespFormat
            this.editForm.apiDesc = data.data.apiDesc
            this.editForm.apiReqContext = data.data.apiReqContext
            this.editForm.apiReqType = data.data.apiReqType
            this.editForm.apiRespContext = data.data.apiRespContext.length
              ? JSON.parse(data.data.apiRespContext)
              : [{ code: 200, desc: 'OK', example: '' }]
            this.$nextTick(() => this.initText())
          }
        } else {
          this.$message.error(data.data || data.msg)
        }
      })
    },
    addResult(index) {
      this.editForm.apiRespContext.splice(index + 1, 0, { code: '', desc: '' })
    },
    deleteResult(index) {
      this.editForm.apiRespContext.splice(index, 1)
    },
    submit() {
      this.$refs.editForm.validate(valid => {
        if (valid) {
          let respContext = this.editForm.apiRespContext
          let resp = new Set()
          respContext.forEach(item => resp.add(item.code))
          if (respContext.length !== resp.size) {
            this.$message.error('返回结果code不能重复')
            return
          }
          let arg = {
            apiId: this.editForm.apiId,
            apiDesc: this.editForm.apiDesc,
            apiNm: this.editForm.apiNm,
            apiPath: this.editForm.apiPath,
            apiReqContext: this.editForm.apiReqContext,
            apiReqType: this.editForm.apiReqType,
            apiRespContext: JSON.stringify(this.editForm.apiRespContext),
            apiRespFormat: this.editForm.apiRespFormat
          }
          this.$ajax({
            url: this.$ajax.setUrl('index/indexApi'),
            method: 'put',
            data: this.$ajax.setData(arg)
          }).then(({ data }) => {
            if (data && data.code === '0') {
              this.$message.success(data.msg)
              this.$emit('confirm')
            } else {
              this.$message.error(data.data || data.msg)
            }
          })
        }
      })
    },
    clearForm() {
      this.editForm.apiId = ''
      this.editForm.apiNm = ''
      this.editForm.apiPath = ''
      this.editForm.apiReqType = ''
      this.editForm.apiRespFormat = ''
      this.editForm.apiDesc = ''
      this.editForm.apiReqContext = ''
      this.editForm.apiRespContext = [{ code: 200, desc: 'OK', example: '' }]
      this.apiReqEditor.toTextArea()
      this.apiReqEditor = null
      this.apiRespEditor.toTextArea()
      this.apiRespEditor = null
      this.$nextTick(() => this.$refs.editForm.clearValidate())
    }
  }
}
</script>

<style lang="scss">
.actual-api-detail {
  .source-item {
    width: 100%;
    height: 45px;
    margin-bottom: 20px;
    box-shadow: #eee 0 0 10px;
    position: relative;
    &.desc-item {
      height: 117px;
      .source-title {
        line-height: 117px;
      }
      .el-textarea__inner {
        height: 117px;
        border-color: #fff;
      }
    }
    .source-title {
      font-weight: bold;
      width: 150px;
      height: 100%;
      padding-left: 50px;
      line-height: 45px;
      color: #fff;
      position: absolute;
      z-index: 2;
      &:before {
        width: 10px;
        height: 10px;
        content: '';
        background-color: #eee9ff;
        border: 2px solid #cfc7ee;
        margin-top: -5px;
        position: absolute;
        top: 50%;
        left: 20px;
        border-radius: 50%;
      }
      &:after {
        width: 0;
        height: 0;
        content: '';
        margin-top: -10px;
        border-top: 10px solid transparent;
        border-bottom: 10px solid transparent;
        position: absolute;
        top: 50%;
        right: -10px;
      }
      &.linear-blue:after {
        border-left: 10px solid #635fd7;
      }
      &.linear-purpose:after {
        border-left: 10px solid #7c6bed;
      }
      &.linear-green:after {
        border-left: 10px solid #36b999;
      }
      &.linear-cyan:after {
        border-left: 10px solid #0696ec;
      }
    }
    .source-content {
      line-height: 45px;
      padding-left: 150px;
    }
    .el-select .el-input__inner,
    .el-input .el-input__inner {
      height: 45px;
      line-height: 45px;
      border-color: #fff;
    }
  }
  .params-item {
    height: 180px;
    border-top-left-radius: 5px;
    border-bottom-left-radius: 5px;
    overflow: hidden;
    .source-title {
      width: 200px;
      padding-left: 0;
      color: #666;
      text-align: center;
      &:before {
        width: 5px;
        height: 100%;
        content: '';
        border: 0;
        margin-top: 0;
        background-color: #f2a85d;
        position: absolute;
        top: 0;
        left: 0;
        border-radius: 0;
      }
      &:after {
        width: 1px;
        height: auto;
        margin-top: 0;
        content: '';
        background-color: #eee;
        position: absolute;
        top: 10px;
        right: 10px;
        bottom: 10px;
      }
      span {
        display: inline-block;
        width: 50px;
        height: 50px;
        margin-top: 45px;
        color: #fff;
        background-color: #f2a85d;
        text-align: center;
        border-radius: 50%;
        svg {
          width: 30px;
          height: 30px;
          margin-top: 10px;
        }
      }
    }
    .source-content {
      padding: 20px 20px 20px 200px;
      line-height: normal;
      .el-form-item__content {
        line-height: normal;
      }
      .CodeMirror {
        height: 140px;
        border: 1px solid #eee;
      }
    }
  }
  .result-wrap {
    .result-title {
      height: 40px;
      color: #fff;
      background-color: #38abf6;
      text-align: center;
      line-height: 40px;
      border-radius: 5px;
      .el-col {
        height: 100%;
        & + .el-col {
          position: relative;
          &::after {
            width: 1px;
            height: 30px;
            content: '';
            background-color: #fff;
            position: absolute;
            top: 5px;
            left: 0;
          }
        }
      }
    }
    .result-item {
      margin-top: 20px;
      padding: 20px 90px 0 0;
      border-top-left-radius: 5px;
      border-bottom-left-radius: 5px;
      position: relative;
      overflow: hidden;
      box-shadow: 0 2px 2px 0 #eee, 0 0 6px #eee;
      &:before {
        width: 5px;
        content: '';
        background-color: #1e9ffe;
        position: absolute;
        top: 0;
        left: 0;
        bottom: 0;
      }
      p {
        font-weight: bold;
        color: 000;
        text-indent: 10px;
        margin-bottom: 10px;
      }
      .el-input__inner {
        border-color: #eee;
      }
      .el-input-number {
        width: 100%;
      }
      .el-input-number__decrease,
      .el-input-number__increase {
        display: none;
      }
      .el-col-8 {
        padding: 0 20px;
      }
      .result-handler {
        width: 90px;
        padding: 0 10px;
        position: absolute;
        top: 20px;
        right: 0;
        .el-button {
          margin-top: 5px;
        }
        .el-button--primary {
          background-color: #38abf6;
          border-color: #38abf6;
        }
      }
      .result-text-box {
        margin-bottom: 5px;
        .el-form-item__content {
          line-height: normal;
        }
        .CodeMirror {
          height: 250px;
          border: 1px solid #eee;
        }
      }
    }
  }
  .disable-item .CodeMirror {
    background-color: #f6f6f6;
  }
  .code-input .el-form-item__error {
    margin-top: -15px;
  }
  .el-input.is-disabled .el-input__icon {
    display: none;
  }
}
</style>
